home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QRZ! Ham Radio 6
/
QRZ Ham Radio Callsign Database - Volume 6.iso
/
mac
/
files
/
amiga
/
csrc720j.lzh
/
timezone.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-21
|
7KB
|
230 lines
/* timezone.c
*/
#include <time.h>
/* Day number of first Sunday in April and last Sunday in October */
int dst_start,dst_end;
int daylight = 0; /* non-zero if local timezone uses DST */
/* Cumulative days per month. Used to figure out first or last Sunday
in a month. For the first Sunday in a month start with the cumulative
number of days in the previous month. For the last Sunday in a month
use the cumulative days for that month minus 7.
The time routine uses Jan 1st as day zero.
*/
int dpm[12] = {31,59,90,120,151,181,212,243,273,304,334,365};
/* Find a timezone string. If s is a non-null string, use it.
Otherwise check for the environment variable TZ_CHU in the system
or Manx.
If there's nothing valid, return -900 which is an impossible number
of minutes for the correction to UTC.
*/
gettz(s)
char *s;
{
register char *p;
extern int zone();
char zonestr[10];
zonestr[0] = 0;
if(s && *s) {
strcpy(zonestr,s);
}
else {
/* Get the local time zone */
p = getenv("TZ_CHU");
if(p)strcpy(zonestr,p);
else {
/* If system one isn't there, try the MANX one */
p = getenv("MANX/TZ_CHU");
if(p)strcpy(zonestr,p);
}
}
if(zonestr[0] == 0) {
printf("ERROR: Timezone is not set in default file nor in TZ_CHU\n");
return(-900); /* -900 is an impossible number of minutes which is
tested for later in the program
*/
}
else {
return(zone(&zonestr[0]));
}
}
/* Get timezone in number of minutes east(-ve) or west(+ve) of Greenwich.
Return number of minutes represented by the string in *s.
Set the daylight flag if the string ends with a valid DST indicator.
*/
zone(s)
char *s;
{
register char *p,sign;
register long adj;
p = s;
while((*p == ' ') || (*p == '\t'))p++;
sign = 1;
if(*p == '-') {
p++;
sign = -1;
}
adj = atoi(p)*60;
while(isdigit(*p))p++;
if(*p == ':') {
p++;
adj += atoi(p);
while(isdigit(*p))p++;
}
switch(*p) {
case 'd': /* North America - begin April to end October */
case 'D':
case 'u': /* U.K. - end March to end October */
case 'U':
case 'e': /* Europe + CIS - end March to end September */
case 'E':
case 'c': /* China - Apr 12 to Sept 12 */
case 'C':
daylight = *p;
}
/* The adjustment cannot exceed 12 hours */
if(adj > 720) {
printf("ERROR: timezone correction is too large\n");
daylight = 0;
return(-900);
}
return(adj*sign);
}
/*
If daylight savings not used, or not currently in effect then just
return the local standard time adjustment. Otherwise correct the
standard time adjustment for daylight savings time.
Need local day of the year (1-366), local hour (0-23)
and standard timezone adjustment in minutes.
*/
dst(adjust)
int adjust;
{
/* adjust is the local standard time in minutes east(-ve) or west(+ve)
of Greenwich. This routine checks to see if daylight savings time
is required and, if so and daylight savings is in effect, the local
standard time is adjusted accordingly
*/
short day,hour;
time_t ltime;
register struct tm *tp;
int dstflag;
if(!daylight)return(adjust);
dstflag = 0;
time(<ime);
tp = localtime(<ime);
day = tp->tm_yday + 1;
hour = tp->tm_hour;
/* Northern Hemisphere */
if((daylight >= 'a') && (daylight <= 'z')) {
if((day < dst_start) || (day > dst_end))return(adjust);
/* Now: if DST is in effect, determine if it should be applied */
if((day > dst_start) && (day < dst_end))dstflag++;
else if((day == dst_end) && (hour < 2))dstflag++;
else if((day == dst_start) && (hour >= 2))dstflag++;
if(dstflag) {
adjust -= 60;
}
}
else {
/* Southern Hemisphere */
if((day > dst_start) && (day < dst_end))return(adjust);
/* Now: if DST is in effect, determine if it should be applied */
if((day < dst_start) || (day > dst_end))dstflag++;
else if((day == dst_end) && (hour < 2))dstflag++;
else if((day == dst_start) && (hour >= 2))dstflag++;
if(dstflag) {
adjust -= 60;
}
}
return(adjust);
}
/*
The definition of DST in North America is the first Sunday in April
to the last Sunday in October.
For the U.K. it is last Sunday in March to last Sunday in October.
For Europe and the CIS, it is the last Sunday in March to last Sunday
in September.
China uses April 12th to Sept 12th.
Australia and New Zealand probably use last Sunday in October to last
Sunday in March, but will have to check this out.
Compute the first Sunday in April and last Sunday in October for the
DST adjustment. Don't bother if daylight flag is not set.
This routine must be called once before dst() is used and in the
unlikely event that your computer never crashes, it must be called
once per year after that.
last_dstyear saves the last year that dstdates was called so you can
add some code to check that the year hasn't changed
*/
int last_dstyear;
dstdates()
{
short days;
time_t ltime;
register struct tm *tp;
short find_sunday;
find_sunday = 1;
if(!daylight)return;
time(<ime);
tp = localtime(<ime);
last_dstyear = tp->tm_year;
switch(toupper(daylight)) {
case 'D':
dst_start = dpm[3]; /* first Sunday in April */
dst_end = dpm[10]-7; /* last Sunday in October */
break;
case 'U':
dst_start = dpm[3] - 7; /* end of March */
dst_end = dpm[10] - 7; /* end of Oct */
break;
case 'E':
dst_start = dpm[3] - 7; /* End of march */
dst_end = dpm[9] - 7; /* End of Sept */
break;
case 'C':
dst_start = dpm[3]+11; /* Apr 12 */
dst_end = dpm[9]+11; /* Sep 12 */
find_sunday = 0; /* Don't look for Sunday */
break;
}
/* Check for leap year */
/* Technically, this calculation is incorrect. It does not check for
years ending in 00 which are not leap years. But the year 2000
IS a leap year, so the error won't hit until the year 2100 and
I won't be around to collect bug reports.
*/
if((tp->tm_year%4) == 0){
dst_start += 1;
dst_end += 1;
}
if(find_sunday) {
days = (dst_start + tp->tm_wday)%7;
if(days)dst_start += 7 - days;
days = (dst_end + tp->tm_wday)%7;
if(days)dst_end += 7 - days;
}
/* Adjust the days so that Jan 1st is day #1 instead of the zero returned
by the localtime() routine
*/
dst_start++;
dst_end++;
}